﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net; 
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
using Newtonsoft.Json.Linq;
using System.Web.Routing;
using Newtonsoft.Json; 

namespace AIResearch.AssistantMvc.Controllers
{
    public class ChatBotController : Controller
    {
        //
        // GET: /ChatBot/
        public ActionResult Index()
        {
            Response.Headers.Add("Access-Control-Allow-Origin", "*");
            Response.Headers.Add("Access-Control-Allow-Methods", "POST");
            Response.Headers.Add("Access-Control-Max-Age", "1000");
            return View();
        }

        public void Post(string sessionId, string q, string data)
        {
            var dd = PostInternal(sessionId, q, data);
            Response.Clear();
            Response.Write(dd);
            Response.ContentType = "Application/json";
            Response.End(); 
        }

        public ActionResult PostMessage(string sessionId, string q)
        { 
            var finalMessage = new List<string>();

            dynamic result = JObject.Parse(Post(sessionId, q));
            var parameters = new Dictionary<string, string>();
            while (result.type != "stop")
            {
                //if (result.type == "merge") 
                //{
                //    if (result.entities != null)
                //    {
                //        var routeValueDict = new RouteValueDictionary(result.entities);
                //        if (routeValueDict.Keys.Count <= 0)
                //            break;

                //        foreach (var key in routeValueDict.Keys)
                //        {
                //            var entity = ((dynamic)routeValueDict[key])[0];
                //            if (entity.confidence > 0.6)
                //            {
                //                parameters[key] = entity.value;
                //            }
                //        }
                //    }
                //} 
                result = JObject.Parse(PostInternal(sessionId, "", JsonConvert.SerializeObject(parameters, Formatting.Indented)));
                if (result.type == "msg") {
                    finalMessage.Add(result.msg.ToString());
                }
            }
            return Json(finalMessage.ToArray(), JsonRequestBehavior.AllowGet);
        }

        private string PostInternal(string sessionId, string message, string parameters )
        {
            var token = "D6W4ZCJ2LUSIQQWZCHWK6EASLA7OYPPL";
            var httpHeaders = new Dictionary<string, string>();
            httpHeaders["Authorization"] = "Bearer " + token;
            var url = "https://api.wit.ai/converse?session_id=" + sessionId;
            if (!string.IsNullOrEmpty(message))
                url += string.Format("&q={0}", HttpUtility.UrlEncode(message));
            var result = WebUtils.DoPost(url, parameters, httpHeaders, WebUtils.ACCEPT_JSON);
            return result;
        }

        private string Post(string sessionId, string message, IDictionary<string,string> parameters = null)
        {
            var token = "D6W4ZCJ2LUSIQQWZCHWK6EASLA7OYPPL";  
            var httpHeaders = new Dictionary<string, string>();
            httpHeaders["Authorization"] = "Bearer " + token;
            var url = "https://api.wit.ai/converse?session_id=" + sessionId;
            if (!string.IsNullOrEmpty(message))
                url += string.Format("&q={0}", HttpUtility.UrlEncode(message));
            var result = WebUtils.DoPost(url, parameters ?? new Dictionary<string,string>(), httpHeaders, WebUtils.ACCEPT_JSON);
            return result;
        }
    }


    public static class WebUtils
    {
        public const string ACCEPT_XML = "application/xml";
        public const string ACCEPT_JSON = "application/json";

        static readonly string ApiUserAgent = "Vision API Client";

        public static string DoPost(string url, string postDataString, IDictionary<string, string> httpHeaders, string accept = ACCEPT_XML)
        {
            var req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.KeepAlive = true;
            req.UserAgent = ApiUserAgent;
            req.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
            req.Accept = string.IsNullOrEmpty(accept) ? ACCEPT_XML : accept;

            if (httpHeaders != null)
            {
                foreach (var key in httpHeaders.Keys)
                {
                    req.Headers[key] = httpHeaders[key];
                }
            }

            var postData = Encoding.UTF8.GetBytes(postDataString);
            var reqStream = req.GetRequestStream();
            reqStream.Write(postData, 0, postData.Length);
            reqStream.Close();

            var rsp = (HttpWebResponse)req.GetResponse();
            var encoding = Encoding.GetEncoding(string.IsNullOrEmpty(rsp.CharacterSet) ? "utf-8" : rsp.CharacterSet);

            return GetResponseAsString(rsp, encoding);
        }


        public static string DoPost(string url, IDictionary<string, string> parameters, IDictionary<string, string> httpHeaders, string accept = ACCEPT_XML)
        {
            return DoPost(url, BuildPostData(parameters),httpHeaders,accept);
        }

        public static string DoGet(string url, IDictionary<string, string> parameters, string accept = ACCEPT_XML)
        {
            if (parameters != null && parameters.Count > 0)
            {
                if (url.Contains("?"))
                {
                    url = url + "&" + BuildPostData(parameters);
                }
                else
                {
                    url = url + "?" + BuildPostData(parameters);
                }
            }

            var req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "GET";
            req.KeepAlive = true;
            req.UserAgent = ApiUserAgent;
            req.ContentType = "application/x-www-form-urlencoded;charset=utf-8";

            req.Accept = string.IsNullOrEmpty(accept) ? ACCEPT_XML : accept;

            var rsp = (HttpWebResponse)req.GetResponse();
            var encoding = Encoding.GetEncoding(string.IsNullOrEmpty(rsp.CharacterSet) ? "utf-8" : rsp.CharacterSet);
            return GetResponseAsString(rsp, encoding);
        }

        private static string GetResponseAsString(HttpWebResponse rsp, Encoding encoding)
        {
            StringBuilder result = new StringBuilder();
            Stream stream = null;
            StreamReader reader = null;

            try
            {
                stream = rsp.GetResponseStream();
                reader = new StreamReader(stream, encoding);

                char[] buffer = new char[256];
                int readBytes = 0;
                while ((readBytes = reader.Read(buffer, 0, buffer.Length)) > 0)
                {
                    result.Append(buffer, 0, readBytes);
                }
            }
            finally
            {
                if (reader != null) reader.Close();
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }

            return result.ToString();
        }

        private static string BuildPostData(IDictionary<string, string> parameters)
        {
            StringBuilder postData = new StringBuilder();
            bool hasParam = false;

            IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
            while (dem.MoveNext())
            {
                string name = dem.Current.Key;
                string value = dem.Current.Value;
                if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value))
                {
                    if (hasParam)
                    {
                        postData.Append("&");
                    }

                    postData.Append(name);
                    postData.Append("=");
                    postData.Append(Uri.EscapeDataString(value));
                    hasParam = true;
                }
            }

            return postData.ToString();
        }
    }
}